﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using DirkRettschlag.Utils;
using System.Drawing.Imaging;

namespace Departure
{
    public partial class ctrlButton : UserControl
    {
        #region Delegates
        
        public delegate void ButtonClickedEventHandler(ctrlButton sender);
        public event ButtonClickedEventHandler OnButtonClicked;
        
        #endregion Delegates

        #region Variables

        string caption = string.Empty;

        StringFormat m_stringFormat;
        SkinSettings skinSettings;
        
        bool vga = false;
        bool selected = false;
        bool toggled = false;

        // Background drawing
        Bitmap backBufferBitmap;
        Graphics backBuffer;

        IImagingFactory iImagingFactory;
        IImage imageButton;
        ImageInfo info;
        IntPtr hdcDest;
        Rectangle rectButton;
        string imagePath;

        #endregion Variables

        #region Enums

        public enum ButtonType
        {
            Normal,
            Toggle
        }

        #endregion Enums

        #region Constructor

        public ctrlButton()
        {
            InitializeComponent();

            CreateBackBuffer();

            iImagingFactory = (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));

            m_stringFormat = new StringFormat();
            m_stringFormat.Alignment = StringAlignment.Near;
            m_stringFormat.FormatFlags = StringFormatFlags.NoWrap;
        }

        public ctrlButton(string caption, bool vga, string ImagePath)
        {
            this.caption = caption;
            this.vga = vga;

            InitializeComponent();

            CreateBackBuffer();

            iImagingFactory = (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));

            m_stringFormat = new StringFormat();
            m_stringFormat.Alignment = StringAlignment.Near;
            m_stringFormat.FormatFlags = StringFormatFlags.NoWrap;

            this.ImagePath = ImagePath;

            iImagingFactory.CreateImageFromFile(ImagePath, out imageButton);
            imageButton.GetImageInfo(out info);
            rectButton = new Rectangle((this.Width - (int)info.Width) / 2, (this.Height - (int)info.Height) / 2, (int)info.Width + ((this.Width - (int)info.Width) / 2), (int)info.Height + ((this.Height - (int)info.Height) / 2));

        }

        #endregion Constructor

        #region Overidden Methods
        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do nothing
        }

        /// <summary>
        /// Paints the control.
        /// </summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (backBuffer != null && skinSettings != null && imageButton != null)
            {
#if DEBUG
                Stopwatch stopWatch = Stopwatch.StartNew();
#endif
                if (vga)
                {
                    if (toggled)
                        backBuffer.DrawImage(skinSettings.BackGroundButtonSelected, new Rectangle(0, 0, this.Width, this.Height), new Rectangle(0, 0, skinSettings.BackGroundButtonSelected.Width, skinSettings.BackGroundButtonSelected.Height), GraphicsUnit.Pixel);
                    else
                        backBuffer.DrawImage(skinSettings.BackGroundButton, new Rectangle(0, 0, this.Width, this.Height), new Rectangle(0, 0, skinSettings.BackGroundButton.Width, skinSettings.BackGroundButton.Height), GraphicsUnit.Pixel);

                    if (selected)
                        backBuffer.DrawLine(new Pen(skinSettings.FontColor), 0, this.Height - 1, this.Width, this.Height - 1);

                    hdcDest = IntPtr.Zero;
                    hdcDest = backBuffer.GetHdc();

                    try
                    {
                        imageButton.Draw(hdcDest, ref rectButton, System.IntPtr.Zero);
                    }
                    catch
                    {
                    }
                    finally
                    {
                        if (hdcDest != IntPtr.Zero)
                            backBuffer.ReleaseHdc(hdcDest);
                    }

                    //using (Font f2 = Utilities.AppropriateFont(backBuffer, 5, 200, this.Size, caption, this.Font, out size))
                    //{
                    //    backBuffer.DrawString(caption, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                    //}

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
                else
                {
                    backBuffer.DrawImage(skinSettings.BackGroundButton, new Rectangle(0, 0, this.Width, this.Height), new Rectangle(0, 0, skinSettings.BackGroundButton.Width, skinSettings.BackGroundButton.Height), GraphicsUnit.Pixel);

                    hdcDest = IntPtr.Zero;
                    hdcDest = backBuffer.GetHdc();

                    try
                    {
                        imageButton.Draw(hdcDest, ref rectButton, System.IntPtr.Zero);
                    }
                    catch
                    {
                    }
                    finally
                    {
                        if (hdcDest != IntPtr.Zero)
                            backBuffer.ReleaseHdc(hdcDest);
                    }

                    //using (Font f2 = Utilities.AppropriateFont(backBuffer, 5, 200, this.Size, caption, this.Font, out size))
                    //{
                    //    backBuffer.DrawString(caption, f2, new SolidBrush(skinSettings.FontColor), (this.Bounds.Width - size.Width) / 2, (this.Bounds.Height - size.Height) / 2);
                    //}

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
#if DEBUG
                stopWatch.Stop();

                Debug.WriteLine("Button Render Time:   " + stopWatch.ElapsedMilliseconds.ToString());
#endif
            }
            else
            {
                base.OnPaint(e);
            }
        }

        /// <summary>
        /// Called when the control is resized.
        /// </summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            rectButton = new Rectangle((this.Width - (int)info.Width) / 2, (this.Height - (int)info.Height) / 2, (int)info.Width + ((this.Width - (int)info.Width) / 2), (int)info.Height + ((this.Height - (int)info.Height) / 2));
            CreateBackBuffer();
            Invalidate();
        }

        protected override void OnClick(EventArgs e)
        {
            if (OnButtonClicked != null)
                OnButtonClicked(this);
            Invalidate();
            base.OnClick(e);
        }

        #endregion Overridden Methods

        #region Properties

        public SkinSettings SkinSettings
        {
            get
            {
                return skinSettings;
            }
            set
            {
                skinSettings = value;
                Invalidate();
            }
        }

        public bool VGA
        {
            get { return this.vga; }
            set 
            {
                this.vga = value; 
                Invalidate();
            }
        }

        public bool Selected
        {
            get { return this.selected; }
            set 
            {
                this.selected = value;
                Invalidate();
            }
        }

        public bool Toggled
        {
            get { return this.toggled; }
            set 
            {
                this.toggled = value;
                Invalidate();
            }
        }
        
        public string Caption
        {
            get
            {
                return this.caption;
            }
            set
            {
                this.caption = value;
            }
        }

        public string ImagePath
        {
            get
            {
                return this.imagePath;
            }
            set
            {
                this.imagePath = value;
                SetImage(this);
            }
        }

        #endregion Properties


        delegate void SetImageCallback(Control co);
        public void SetImage(Control co)
        {
            if (co.InvokeRequired)
            {
                SetImageCallback d = new SetImageCallback(SetImage);
                co.Invoke(d, new object[] { co });
            }
            else
            {
                try
                {
                    iImagingFactory.CreateImageFromFile(imagePath, out imageButton);
                    imageButton.GetImageInfo(out info);
                    rectButton = new Rectangle((this.Width - (int)info.Width) / 2, (this.Height - (int)info.Height) / 2, (int)info.Width + ((this.Width - (int)info.Width) / 2), (int)info.Height + ((this.Height - (int)info.Height) / 2));
                    Invalidate();
                }
                catch
                {
                }
            }

        }

        /// <summary>
        /// Cleans up the background paint buffer.
        /// </summary>
        private void CleanupBackBuffer()
        {

            if (backBufferBitmap != null)
            {
                backBufferBitmap.Dispose();
                backBufferBitmap = null;
                backBuffer.Dispose();
                backBuffer = null;
            }

        }

        /// <summary>
        /// Creates the background paint buffer.
        /// </summary>
        private void CreateBackBuffer()
        {
            CleanupBackBuffer();

            backBufferBitmap = new Bitmap(Bounds.Width, Bounds.Height);
            backBuffer = Graphics.FromImage(backBufferBitmap);
        }
    }
}